package org.ifi.xechecs.transtable;

import org.ifi.xechecs.board.Board;
import org.ifi.xechecs.board.Piece;


public class Zobrist
{
    private static long  randomBitStrings[];
    private static final int N_BIT_STRINGS = 840;

    static
    {
    	//no cache for castling and en passant
        randomBitStrings = new long [N_BIT_STRINGS];
        java.util.Random random = new java.util.Random();
        for(int i=0; i < N_BIT_STRINGS; i++)
        {
            randomBitStrings[i] = random.nextLong();
        }
    }
    
    
    /**
     * Static method that generates a zobrist hash from a GameState using the
     * bitString set generated statically above.
     *
     * @param   board       the GameState from whom to construct a key
     * @return  the hash code
     */
    public static long hash(Board board)
    {
        // Initialize hash
        long hash = 0;
        // First the board position
        // There are 832 bitStrings for this part
        // 13 different ways each square can be
        byte p;
        byte i;
        int k;
        for(i = 0; i < 64; i++)
        {
            p = board.getPiece(i);
            // Now we have 0 <= i < 64 and 0 <= j < 13
            // We need k such that 0 <= k < 832
            // therefore,
            k = i*13 + p;
            // Now XOR the corresponding bitString to the hash
            hash = hash ^ randomBitStrings[k];
        }
        // Now we see the other components
        if( board.getCurrentPlayer() == Piece.WHITE ){
            hash = hash ^ randomBitStrings[832];
        }else{
            hash = hash ^ randomBitStrings[833];
        }
        if( !board.isCastledWhite() ){
            hash = hash ^ randomBitStrings[834];
        }else{
            hash = hash ^ randomBitStrings[835];
        }
        if( !board.isCastledBlack() ){
            hash = hash ^ randomBitStrings[836];
        }else{
            hash = hash ^ randomBitStrings[837];
        }
//        if( state.canCastleWhiteQueenside() )
//            hash = hash ^ bitStrings[838];
//        else
//            hash = hash ^ bitStrings[839];
//        if( state.canCastleBlackQueenside() )
//            hash = hash ^ bitStrings[840];
//        else
//            hash = hash ^ randomBitStrings[841];
        if( board.getEnPassant() == -1 ){
            hash = hash ^ randomBitStrings[838];
        }else{
            hash = hash ^ randomBitStrings[839+board.getEnPassant()];
    	}
        // That's it! We're done..
        return Math.abs(hash);
    }
 
 
}